//
//  IStarDemoUtils.m
//  ios_expertApp
//
//  Created by flannery on 2019/6/10.
//  Copyright © 2019年 com.isstashine.www. All rights reserved.
//

#import "IStarDemoUtils.h"
#import "pthread.h"
#import "UIKit/UIKit.h"
@class ClassB;


typedef void(^blockLearning)(void);

@interface Animal : NSObject <NSCoding>
@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) NSInteger age;

@property (nonatomic, copy) void(^blockAnimal)(void);
-(Animal *(^)(int))sleep;
@end
@implementation Animal

//神明一个方法，他的返回值是block，block里面的返回值是Animal，且带有参数
- (Animal *(^)(int))sleep{
    // 第一个return，返回的e是block，sleep这个方法的返回值
    return ^(int a){
        NSLog(@"睡着了！！睡了%d光年", a);
        // 第二个return，返回的是block的返回值，我们设定的Animal类
        return self;
    };
}

- (void)encodeWithCoder:(NSCoder *)coder
{
    [coder encodeObject:self.name forKey:@"name"];
    [coder encodeInteger:self.age forKey:@"age"];
}

- (instancetype)initWithCoder:(NSCoder *)coder
{
    self.name = [coder decodeObjectForKey:@"name"];
    self.age = [coder decodeIntegerForKey:@"age"];
    return self;
}

@end

@interface ClassA : NSObject
@property (nonatomic, copy) ClassB *objB;
@property (nonatomic, copy) blockLearning myBlock;

-(void) doSomething;
@end
@implementation ClassA
- (void)doSomething{};
@end

//classB
@interface ClassB : NSObject
@property (strong, nonatomic) ClassA *objA;
@property (nonatomic, copy) blockLearning myBlock;

-(void)doSomething;
@end

@implementation ClassB
- (void)doSomething{
    
}
@end

@interface IStarDemoUtils()
@property (nonatomic, copy) void(^blockProperty)(void);
@property (nonatomic, strong) Animal *animal;

-(void)eat:(void(^)(void))paramterBlock;
-(void)eat2:(void(^)(NSString *apple))paramterBlock;
-(void(^)(void))look;
-(void(^)(int))run222;

@property(nonatomic, strong) void(^MyBlock3)(void); //定义一个block属性

@property (nonatomic, copy) blockLearning myBlockLearning;
@property (nonatomic, copy) NSString *blockStringLearning;

-(void)doSomething;

@end
@implementation IStarDemoUtils

-(void)test020 {
    //获取主队列（主线程）
    NSOperationQueue *queue = [NSOperationQueue mainQueue];
    //创建a,b,c操作
    NSOperation *c = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"OpeartionC");
    }];
    NSOperation *a = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"OpeartionA");
    }];
    NSOperation *b = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"OpeartionB");
    }];
    //添加操作依赖，c依赖于a和b，这样c一定会在a和b完成后才执行，即顺序为A,b,c
    [c addDependency:a];
    [c addDependency:b];
    //添加操作a,b,c到操作队列queue(特意将c在a和b之前添加)
    [queue addOperation:c];
    [queue addOperation:a];
    [queue addOperation:b];
}

-(void)test019{
    //NSBlockOperation初始化
    NSBlockOperation *blkOperation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"NSBlockOperationA %@", [NSThread currentThread]);
    }];
    [blkOperation addExecutionBlock:^{
        NSLog(@"NSBlockOperarionB %@", [NSThread currentThread]);
    }];
    [blkOperation addExecutionBlock:^{
        NSLog(@"NSBlockOperationC %@", [NSThread currentThread]);
    }];
    [blkOperation start];
}

-(void)test018{
    //NSInvocationOpeartion初始化
    NSInvocationOperation *invoOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
    [invoOperation start];
    
    //NSBlockOpertion初始化
    NSBlockOperation *blkOperation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"NSBLockOperation");
    }];
    [blkOperation start];
}

-(void)test017{
    // 定义延迟时间：3s
    dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0*NSEC_PER_SEC));
    dispatch_after(delay, dispatch_get_main_queue(), ^{
        //要执行任务...
    });
    
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, queue, ^{
        //操作1
    });
    dispatch_group_async(group, queue, ^{
        //操作2
    });
    dispatch_group_async(group, queue, ^{
        //操作3
    });
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        //后续操作
    });
}

/**
 ** IOS网络编程与多线程基础
 ** IOS网络编程与多线程基础
 ** IOS网络编程与多线程基础
 ** IOS网络编程与多线程基础
 **/
+(instancetype)sharedInstance{
    static dispatch_once_t once = 0;
    static id sharedInstance = nil;
    dispatch_once(&once, ^{
        //只实例化一次
        sharedInstance = [[self alloc]init];
    });
    return sharedInstance;
}

-(void)test016{
    // 1. 提交异步任务
    NSLog(@"开始提交异步任务");
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //耗时任务
        [NSThread sleepForTimeInterval:10];
    });
    NSLog(@"异步任务提交成功!");
    
    // 2. 提交同步任务
    NSLog(@"开始提交同步任务");
    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //耗时任务
        [NSThread sleepForTimeInterval:10];
    });
    NSLog(@"同步任务提交成功!");
    
    
    //创建一个并发队列
    dispatch_queue_t concurrent_queue = dispatch_queue_create("demo.gcd.concurrent_queue", DISPATCH_QUEUE_CONCURRENT);
    //创建一个串行队列
    dispatch_queue_t serial_queue = dispatch_queue_create("demo.gcd.serial_queue", DISPATCH_QUEUE_SERIAL);
    
    //获取主队列（在主线程上执行）
    dispatch_queue_t main_queue = dispatch_get_main_queue();
    //获取不同优先级的全局队列（优先级从高到低）
    dispatch_queue_t queue_high = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
    dispatch_queue_t queue_default = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_queue_t queue_low = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
    dispatch_queue_t queue_background = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
}




- (void)doSomething{
    
    ClassA *objA = [[ClassA alloc] init];
    __weak typeof(objA) weakObjA = objA;
    self.myBlockLearning = ^{
        __strong typeof(weakObjA) strongWeakObjA = weakObjA;
        [strongWeakObjA doSomething];
    };
    
    
    
    [self testWithBlock:^{
        [self test];
    }];
}

-(void)testWithBlock:(void(^)(void))block{
    self.myBlockLearning();
}

-(void)test{
    NSLog(@"test");
}

-(void)testBlockRetainCycle{
    ClassB *objB = [[ClassB alloc] init];
    __weak  typeof(objB) weakObjB = objB;
    self.myBlockLearning = ^{
        [weakObjB doSomething];
    };
    objB.objA = ClassA.new;
    objB.myBlock();
    objB.myBlock = nil;
}

-(void)test016BlockLearning {
    __weak typeof(self) weakSelf3 = self;
    self.myBlockLearning = ^{
        //其实注释中的代码，同样会造成循环应用
        NSString *localStirng = weakSelf3.blockStringLearning;
    };
    
    dispatch_async(dispatch_get_main_queue(), ^{
        [self doSomething];
    });
}

- (void (^)(int))run222{
    return ^(int m){
        NSLog(@"跑起来了！！跑了%dkm", m);
    };
}

// 申明一个方法，他的返回值是block，block里无返回值、无参数
- (void (^)(void))look{
    return ^(){
        NSLog(@"你看到了什么");
    };
}

- (void)eat2:(void (^)(NSString *))paramterBlock{
    paramterBlock(@"苹果");
}

- (void)eat:(void (^)(void))paramterBlock{
    self.animal.blockAnimal();
    self.blockProperty();
}

/**
 ** block
 ** block
 ** block
 ** block
 **/
-(void)test015Block{
    
    __weak typeof(self) weakself2 = self;
    self.MyBlock3 = ^{
        weakself2.animal.sleep(1);
    };
    
    __weak typeof(self) weakself = self; //block外面写一个weakself
    //定义一个block
    void(^MyBlock2)(void) = ^(){
        NSLog(@"this ia a block");
        weakself.animal.sleep(3);
    };
    MyBlock2();
    
    self.animal.sleep(1).sleep(2).sleep(3).sleep(4).sleep(5).sleep(6);
    
    self.run222(222);
    
    // p.look执行后返回值是一个block，我们用一个block来接收
    void(^lookBlock)(void) = self.look;
    // 这是调用block的语法！！
    lookBlock();
    // 究极进化以后，就是这个样子
    self.look();
    
    self.look();
    
    [self eat2:^(NSString *apple) {
        NSLog(@"土豪刚买了一个%@x",apple);
    }];
    
    [self eat:^{
        
    }];
    
    self.blockProperty();
    self.animal.blockAnimal();
    
    void(^MyBlock)(void) = ^() {
        NSLog(@"hello block!");
    };
    MyBlock();
}

/**
 ** 多线程
 ** 多线程
 ** 多线程
 ** 多线程
 **/
-(void)test014pthread{
    //NSThread静态工具方法
    // 1. 是否开启了多线程
    BOOL isMultiThreaded = [NSThread isMultiThreaded];
    // 2. 获取当前线程
    NSThread *currentThread = [NSThread currentThread];
    // 3. 获取主线程
    NSThread *mainThread = [NSThread mainThread];
    // 4. 睡眠当前线程
    // 4.1 线程睡眠5s
    [NSThread sleepForTimeInterval:5];
    // 4.2 线程睡眠到指定时间，效果同上
    [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:5]];
    // 5. 退出当前线程，注意不要再主线程调用，防止主线程被kill掉
    // [NSThread exit];
    
    //NSThread线程对象的基本创建，target为入口方法所在的对象，selector为线程入口方法
    // 1. 线程实例对象创建于设置
    NSThread *newThread = [[NSThread alloc] initWithTarget:self selector:@selector(test014run) object:nil];
    
    //设置线程优先级threadPriority(0~1.0),该属性即将被抛弃，将使用qualityOfService代替
//    newThread.threadPriority = 1.0;
    newThread.qualityOfService = NSQualityOfServiceUserInteractive;
    //开启线程
    [newThread start];
    // 2. 静态方法快速创建并开启新线程
    [NSThread detachNewThreadSelector:@selector(test014run) toTarget:self withObject:nil];
    
    [NSThread detachNewThreadWithBlock:^{
        NSLog(@"block run...");
    }];
    
    // NSObject 基类隐式创建线程的一些静态工具方法
    //1. 在当前线程上执行方法，延迟2s
    [self performSelector:@selector(test014run) withObject:nil afterDelay:2.0];
    //2. 在指定线程上执行方法，不等待当前线程
    [self performSelector:@selector(test014run) onThread:newThread withObject:nil waitUntilDone:NO];
    //3. 后台异步执行方法
    [self performSelectorInBackground:@selector(test014run) withObject:nil];
    //4.在主线程上执行方法
    [self performSelectorOnMainThread:@selector(test014run) withObject:nil waitUntilDone:NO];
}

-(void)test014run{
    
}

/**
 ** 数据化存储
 ** 数据化存储
 ** 数据化存储
 ** 数据化存储
 **/

-(void)test012archiver{
    Animal *person = [Animal new];
    person.name = @"Jack";
    person.age = 30;
    
    /*获取文件路径*/
    NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    NSString *path = [documents stringByAppendingPathComponent:@"person.archiver"];
    //归档
    [NSKeyedArchiver archiveRootObject:person toFile:path];
}

-(void)test013unarchiver{
    //获取文件路径
    NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    NSString *path = [documents stringByAppendingPathComponent:@"person.archiver"];
    id obj = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
    NSLog(@"%@", obj);
}

-(void)test010archiver1{
    Animal *person = [Animal new];
    person.name = @"jack";
    person.age = 30;
    
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:person];
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:data forKey:@"person"];
}

-(void)test011unarchiver1{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSData *data = [defaults objectForKey:@"person"];
    /*解档*/
    id obj = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    NSLog(@"%@", obj);
}

-(void)test008userDefaultSaveImage{
    UIImage *img = [UIImage imageNamed:@"1"];
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSData *data = UIImageJPEGRepresentation(img, 1);
    [defaults setObject:data forKey:@"img"];
}

-(void)test009userDefaultGetImage{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    /*转化为NSData对象*/
    NSData *data = [defaults objectForKey:@"img"];
    /*转化为UIImage对象*/
    UIImage *img = [UIImage imageWithData:data];
    UIView *view = UIView.new;
    view.layer.contents = (id)img.CGImage;
}

-(void)test006userDefaultSave{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:@"jack" forKey:@"name"];
    [defaults setInteger:10 forKey:@"age"];
    if([defaults synchronize]) {
        NSLog(@"保存成功");
    }
}

-(void)test007userDefaultGet{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSString* name = [defaults objectForKey:@"name"];
    NSInteger age = [defaults integerForKey:@"age"];
}

-(void)test005{
    //Documents
    NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    //Library
    NSString *cacheDirectory = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    //tmp
    NSString *tmpDirectory = NSTemporaryDirectory();
    
    
    // 1. 获取Home目录路径：
    NSString *homeDir = NSHomeDirectory();
    //2. 获取Documents目录路径：
    NSArray *docpaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *docDir = [docpaths objectAtIndex:0];
    //3. 获取Library/Caches目录路径：
    NSArray *cachepaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *cachesDir = [cachepaths objectAtIndex:0];
    //4. 获取tmp目录路径
    NSString *tmpDir =NSTemporaryDirectory();
    //5.获取应用程序包中资源文件路径（获取程序包中一个图片资源‘img。png’的路径）
    NSString *imgPath = [[NSBundle mainBundle] pathForResource:@"img" ofType:@"png"];
    UIImage *image = [[UIImage alloc] initWithContentsOfFile:imgPath];
}

// 多对象归档
-(void)test004{
    NSString *homeDirectory = NSHomeDirectory();
    NSString *homePath = [homeDirectory stringByAppendingPathComponent:@"testArchiver"];
    
    /*待归档的数据*/
    NSInteger intVal = 1;
    NSString *strVal = @"string";
    CGPoint pointVal = CGPointMake(1.0, 1.0);
    /*初始化归档工具*/
    NSMutableData *mulData = [[NSMutableData alloc]init];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:mulData];
    /*归档*/
    [archiver encodeInteger:intVal forKey:@"key_integer"];
    [archiver encodeObject:strVal forKey:@"key_string"];
    [archiver encodeCGPoint:pointVal forKey:@"key_point"];
    [archiver finishEncoding];
    
    /*归档的数据写入*/
    [mulData writeToFile:homePath atomically:YES];
    /*解归档*/
    NSMutableData *undata = [[NSMutableData alloc] initWithContentsOfFile:homePath];
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:undata];
    CGPoint unpointVal = [unarchiver decodeCGPointForKey:@"key_point"];
    NSString *unstrVale = [unarchiver decodeObjectForKey:@"key_string"];
    NSInteger unintegerVal = [unarchiver decodeIntegerForKey:@"key_integer"];
    [unarchiver finishDecoding];
}

// 3. Archive
-(void)test003{
    /*沙盒根目录*/
    NSString *homeDirectory = NSHomeDirectory();
    /*拼接根目录和自定义文件名构建存储路径*/
    NSString *homePath = [homeDirectory stringByAppendingPathComponent:@"testArchiver"];
    /*待归档的数组，也可归档NSString，NSInteger等基础对象类型*/
    NSArray *array = @[@"obj1", @"obj2", @"obj3"];
    /*归档并返回归档是否成功*/
    BOOL flag = [NSKeyedArchiver archiveRootObject:array toFile:homePath];
    NSArray *unarchivedArchive;
    /*如果归档成功，z那么解归档*/
    if (flag) {
        unarchivedArchive = [NSKeyedUnarchiver unarchiveObjectWithFile:homePath];
    }
    NSLog(@"%@", unarchivedArchive);
}

-(void)test001{
    /**获取NSUserDefaults标准函数对象*/
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    /*存储新对象数据或更新对象数据*/
    [defaults setObject:@"data" forKey:@"key1"];
    /*通过key值去除对象数据*/
    [defaults objectForKey:@"key1"];
    
    /*其他类型的数据存储*/
    [defaults setDouble:3.1415926 forKey:@"double1"];
    [defaults doubleForKey:@"double1"];
    
    [defaults setBool:NO forKey:@"bool1"];
    [defaults boolForKey:@"bool1"];
    
    [defaults setInteger:2016 forKey:@"int1"];
    [defaults integerForKey:@"int1"];
    
    [defaults setFloat:3.14 forKey:@"float1"];
    [defaults floatForKey:@"float1"];
    
    [defaults removeObjectForKey:@"key1"];
}

-(void)test002{
    /**1.读取工程中的plist文件，这里设置的工程plist是一个Dictionary，也可以用Array plist*/
    NSMutableDictionary *data = [[NSMutableDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"test" ofType:@"plist"]];
    NSLog(@"从工程plist读取的数据：%@",data);
    
    [data setObject:@"4444" forKey:@"d"];
    NSLog(@"将要写入沙盒的数据:%@", data);
    /*获取沙盒路径，这里/demo.plist是指新建的沙盒里plist文件路径，一定要加/*/
    NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"/demo.plist"];
    /*2.将更新了的工程中的数据写入沙盒*/
    [data writeToFile:filePath atomically:YES];
    
    /*3.读取沙盒数据*/
    NSMutableDictionary *dic = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath];
    NSLog(@"从沙盒读取的数据：%@", dic);
}

-(void)testNotification{
    [[NSNotificationCenter defaultCenter] addObserverForName:@"block" object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
        NSLog(@"block方式收到系统通知");
    }];
    
    //取消注册通知
//    [[NSNotificationCenter defaultCenter]removeObserver:self];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"block" object:nil];
    
    //发送通知
    [[NSNotificationCenter defaultCenter] postNotificationName:@"block" object:nil];
}


-(void)testtest{
    NSError * error;
    NSString* textFileContents = [NSString stringWithContentsOfFile:@"filePath" encoding:NSASCIIStringEncoding error:&error];
    if(error.code == 0) {
        NSLog(@"%@", textFileContents);
    } else {
        NSLog(@"");
    }
}

-(void)testddddd{
    //测试提交
}
@end
